
from flask import current_app
import jwt
from jwt import exceptions
import datetime
from app.libs.exception import AuthFailed
from app.models.user import User


class TokenService:

    # 构造header
    headers = {
        'typ': 'jwt',
        'alg': 'HS256'
    }

    @classmethod
    def create_token(cls, user: User) -> str:
        # 构造payload
        payload = {
            'id': user.id,
            'nickname': user.nickname,
            'account': user.account,
            'password': user.password,  # 自定义用户ID
            'scope': user.scope,
            # 'refresh_exp':  # @RISK 没有刷新的机制
            # 超时时间
            'exp': datetime.datetime.utcnow() + datetime.timedelta(**current_app.config['TOKEN_EXPIRE'])
        }
        return jwt.encode(payload=payload, key=current_app.config['TOKEN_SALT'],
                          algorithm="HS256", headers=cls.headers)
        #   .decode('utf-8')

    @classmethod
    def verify_jwt_and_get_user(cls, token: str, secret: str = None) -> User:
        """
        检验jwt
        :param token: jwt
        :param secret: 密钥
        :return: dict: payload
        """
        if not secret:
            secret = current_app.config['JWT_SECRET']

        try:
            payload = jwt.decode(token, secret, algorithms=cls.headers['alg'])
            return User().set_attr(payload)
        except exceptions.ExpiredSignatureError:  # 'token已失效'
            raise AuthFailed('token过期，请重新获取')
        except jwt.DecodeError:  # 'token认证失败'
            raise AuthFailed('toke认证失败')
        except jwt.InvalidTokenError:  # '非法的token'
            raise AuthFailed('非法token')
